﻿/***************************************************************
 * Name:      http_base.cpp
 * Purpose:   HTTP协议请求响应基类
 * Author:    杨卓荦 (yzl@bang5.net)
 * Created:   2010-08-29
 * Copyright: 杨卓荦 (http://www.bang5.net)
 * License:
 **************************************************************/

#include "http_base.h"

using namespace std;

HttpBase::HttpBase() { }

HttpBase::~HttpBase() { }

//sfile begin with '/'
bool HttpBase::SendHttpHeadRequest(const char* host,
                                   const char* file,
                                   const char* referer) {
  char outbuf[2048] = {0};
  char buf[512] = {0};

  sprintf(buf, "HEAD %s HTTP/1.1\r\n", file);
  strcpy(outbuf, buf);

  MakeRequestBody(outbuf, host, referer);

  strcat(outbuf, "Pragma: no-cache\r\n");
  strcat(outbuf, "Cache-Control:no-cache\r\n");
  strcat(outbuf, "Connection: close\r\n\r\n");

  return Write(outbuf, strlen(outbuf));
}

//sfile begin with '/'
bool HttpBase::SendHttpGetRequest(const char* host,
                                  const char* file,
                                  const long long int offset,
                                  const char* referer) {
  char outbuf[ 2048 ] = {0};
  char buf[ 512 ] = {0};

  sprintf(buf, "GET %s HTTP/1.1\r\n", file);
  strcpy(outbuf, buf);

  MakeRequestBody(outbuf, host, referer);

  strcat(outbuf, "Connection: close\r\n");
  sprintf(buf, "Range: bytes=%lld-\r\n\r\n", offset);
  strcat(outbuf, buf);

  return Write(outbuf, strlen(outbuf));
}

//sfile begin with '/'
bool HttpBase::SendHttpGetRequest(const char* host,
                                  const char* file,
                                  const char* referer) {
  char outbuf[2048] = {0};
  char buf[512] = {0};

  sprintf(buf, "GET %s HTTP/1.1\r\n", file);
  strcpy(outbuf, buf);

  MakeRequestBody(outbuf, host, referer);

  strcat(outbuf, "Connection: close\r\n\r\n");

  return Write(outbuf, strlen(outbuf));
}

/*
从缓存中提取一个命令行放在line中，返回的是行的长度，line有128字节空间
如果缓冲中没有行结束就返回-1
*/
int HttpBase::GetBufLine(char *buf, int maxpos, char *line) {
  const int kMaxLine = 256;
  for ( int i = 0;i <= maxpos - 2;i++ ) {
    if ( buf[i] == '\r' && buf[i + 1] == '\n' ) {
      memcpy(line, buf, i > kMaxLine - 3 ? kMaxLine - 2 : i);
      line[i > kMaxLine - 2 ? kMaxLine - 1 : i] = 0;
      return i + 2;
    }
  }
  return -1;
}

void HttpBase::AddCookie(string cookie) {
  cookies.push_back( cookie );
}

void HttpBase::MakeRequestBody(char* outbuf, const char* host, const char* referer) {
  char buf[ 512 ] = {0};
  strcat(outbuf,
         "User-Agent: Mozilla/4.0(compatible;MSIE 5.00;Windows 98)\r\n"
         "Accept: */*\r\n");

  sprintf(buf, "Host: %s\r\n", host);
  strcat(outbuf, buf);

  sprintf(buf, "Referer: %s\r\n", referer);
  strcat(outbuf, buf);

  //遍历 cookies 链表
  for (list<string>::iterator i = cookies.begin(); i != cookies.end(); ++i) {
    sprintf(buf, "Cookie: %s\r\n", i->c_str());
    strcat(outbuf, buf);
  }
}

bool HttpBase::Connect(wxString server, int port) {
  wxIPV4address address;
  address.Hostname(server);
  address.Service(port);
  socket.Connect(address);
  return socket.IsConnected();
}

bool HttpBase::Connect(string server, int port) {
  wxString server_wx_str(server.c_str(), wxConvUTF8);
  return Connect(server_wx_str, port);
}

bool HttpBase::Write(const char* buffer, int length) {
  return !socket.Write(buffer, length).Error();
}

int HttpBase::Read(char* buffer, int length) {
  socket.Read(buffer, length);
  return socket.LastCount();
}

void HttpBase::Close() {
  socket.Close();
}
